﻿
/**
 * nPnP - neither Perl not PHP
 *
 * Copyright (C) 2009 Christian Moeller
 *
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the 
 * Free Software Foundation; either version 3 of the License, or (at your option) 
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; 
 * if not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FParser.Parser
{
    public class Tokenizer
    {
        private string code;

        public Tokenizer(string _code)
        {
            this.code = _code;
        }

        public List<Token> Tokenize()
        {
            return Tokenize(false);
        }

        public List<Token> Tokenize(bool StripSpaces)
        {
            List<Token> tokens = new List<Token>();
            sourcePos = -1;

            Token token;

            while ((token = nextToken()).tokenType != EnumTokenType.END)
            {
                if ((StripSpaces && token.tokenType != EnumTokenType.WHITESPACE) ||
                    !StripSpaces)
                    tokens.Add(token);
            }

            return tokens;
        }

        int sourcePos;
        private Token nextToken()
        {
            Token token = new Token();
            token.pos = sourcePos;
            token.data = "";

            if (sourcePos >= (code.Length - 1))
            {
                token.tokenType = EnumTokenType.END;
                return token;
            }

            while (sourcePos < (code.Length -1 ))
            {
                sourcePos++;

                if (token.data.Length > 0 && (
                    Enum.IsDefined(typeof(EnumTokenType), (int)code[sourcePos]) ||
                    code[sourcePos] == (char)EnumTokenType.DQUOTES ||
                    code[sourcePos] == (char)EnumTokenType.WHITESPACE))
                {
                    sourcePos--;
                    token.tokenType = EnumTokenType.DATA;
                    return token;
                }

                if (code[sourcePos] == (char)EnumTokenType.DQUOTES)
                {
                    sourcePos++;
                    while (code[sourcePos] != (char)EnumTokenType.DQUOTES)
                    {
                        token.data += code[sourcePos];
                        sourcePos++;
                    }
                    token.tokenType = EnumTokenType.DQUOTES;
                    return token;
                }
                else if (code[sourcePos] == (char)EnumTokenType.WHITESPACE)
                {
                    while (code[sourcePos + 1] == (char)EnumTokenType.WHITESPACE) { sourcePos++; }
                    token.tokenType = EnumTokenType.WHITESPACE;
                    return token;
                }
                else if (Enum.IsDefined(typeof(EnumTokenType), (int)code[sourcePos]))
                {
                    token.tokenType = (EnumTokenType)(int)code[sourcePos];
                    return token;
                }
                else
                {
                    if (code[sourcePos] != '\r' && code[sourcePos] != '\n'
                        && code[sourcePos] != '\t')
                        token.data += code[sourcePos];
                }
            }
            return token;
        }
    }
}
